<template>
  <div>
    <div class="n-layout-page-header">
      <n-card :bordered="false" title="我的申请"></n-card>
    </div>
    <n-grid x-gap="12" :cols="8">
      <n-gi span="2">
        <n-card :bordered="false" title="发起流程" class="mt-4 proCard">
          <n-scrollbar style="max-height: 68vh">
            <n-grid :x-gap="8" :y-gap="8" :cols="1">
              <n-gi v-if="groupList.length > 0" v-for="item in groupList" :key="item.id">
                <div style="margin-bottom: 12px">
                  <CustomTitle :title="item.groupName" />
                  <n-grid
                    :x-gap="8"
                    :y-gap="8"
                    :cols="2"
                    style="margin-top: 10px"
                    v-if="
                      modelList.filter((x) => x.flowModelGroup === item.id).length > 0
                    "
                  >
                    <n-gi
                      v-for="item in modelList.filter(
                        (x) => x.flowModelGroup === item.id
                      )"
                      :key="item.id"
                    >
                      <ModelCard
                        :id="item.id"
                        :name="item.flowModelName"
                        :icon="item.flowModelIcon"
                        :custonFunction="handleApplyFlow.bind(null, item)"
                      />
                    </n-gi>
                  </n-grid>
                  <n-grid
                    :x-gap="8"
                    :y-gap="8"
                    :cols="1"
                    style="margin-top: 10px"
                    v-if="
                      modelList.filter((x) => x.flowModelGroup === item.id).length === 0
                    "
                  >
                    <n-gi>
                      <MossEmpty />
                    </n-gi>
                  </n-grid>
                </div>
              </n-gi>
              <n-gi v-if="groupList.length === 0">
                <MossEmpty />
              </n-gi>
            </n-grid>
          </n-scrollbar>
        </n-card>
      </n-gi>
      <n-gi span="6">
        <n-card :bordered="false" class="mt-4 proCard">
          <BasicForm @register="register" @submit="handleSubmit" @reset="handleReset">
            <template #statusSlot="{ model, field }">
              <n-input v-model:value="model[field]" />
            </template>
          </BasicForm>
          <BasicTable
            :columns="columns"
            :request="loadDataTable"
            :row-key="(row) => row.id"
            ref="actionRef"
            :actionColumn="actionColumn"
            @update:checked-row-keys="onCheckedRow"
            id="moss-basicTable"
            :bordered="false"
          >
            <template #action>
              <TableAction />
            </template>
          </BasicTable>
        </n-card>
      </n-gi>
    </n-grid>

    <n-drawer v-model:show="showModal" :width="720" :mask-closable="false">
      <n-drawer-content :title="editTitle" :native-scrollbar="false">
        <GenerateForm
          ref="generateFormRef"
          :data="widgetForm"
          :disabled="opsType === 'detail' ? true : false"
        />
        <n-collapse arrow-placement="right" @item-header-click="handleItemHeaderClick">
          <n-collapse-item name="1" v-if="opsType !== 'detail'">
            <template #header>
              <n-text type="info">展开流程配置</n-text>
            </template>
            <n-timeline :icon-size="40">
              <n-timeline-item
                v-for="item in tasks"
                :key="item.id"
                type="info"
                :title="item.name"
                :time="item.desc !== null ? item.desc : '添加抄送人'"
              >
                <template #icon>
                  <n-icon>
                    <n-avatar round size="large" :src="item.approvalUsers[0].avatar" />
                  </n-icon>
                </template>
                <template v-if="item.ccUsers !== null && !item.isApplicant" #default>
                  <div class="custom-flow-cc">
                    <n-avatar size="large">抄送给</n-avatar>
                  </div>
                  <n-icon
                    v-for="x in item.ccUsers"
                    :key="x.taskId"
                    style="margin-right: 45px"
                  >
                    <n-avatar round size="large" :src="x.avatar" />
                  </n-icon>

                  <n-popover trigger="click">
                    <template #trigger>
                      <n-avatar
                        style="cursor: pointer"
                        round
                        size="large"
                        @click="handleShowCcToUser(item.taskId)"
                      >
                        <n-icon size="20"><PlusOutlined /></n-icon>
                      </n-avatar>
                    </template>
                    <div style="width: 450px">
                      <div style="margin-bottom: 10px">
                        <n-input
                          placeholder="输入用户姓名回车搜索"
                          clearable
                          @change="handleChange"
                        >
                          <template #prefix>
                            <n-icon><SearchOutlined /></n-icon>
                          </template>
                          <template #suffix>
                            <n-icon><EnterOutlined /></n-icon>
                          </template>
                        </n-input>
                      </div>
                      <BasicTable
                        :columns="userColumns"
                        :request="loadUserDataTable"
                        :row-key="(row) => row.id"
                        ref="actionUserRef"
                        id="moss-basicTable-ccToUser"
                        :bordered="false"
                        :actionColumn="actionColumnCcToUser"
                        :max-height="200"
                        :showTopOps="false"
                      >
                        <template #action>
                          <TableAction />
                        </template>
                      </BasicTable>
                    </div>
                  </n-popover>
                </template>
              </n-timeline-item>
            </n-timeline>
          </n-collapse-item>
        </n-collapse>
        <n-timeline v-if="opsType === 'detail'" :icon-size="40">
          <n-timeline-item
            v-for="item in detailTasks"
            :key="item.id"
            :title="item.name"
            type="success"
            :time="item.applyTime"
          >
            <template #header>
              <span v-if="item.isApplicant">
                <n-tag>发起审批</n-tag>
              </span>
              <span v-if="!item.isApplicant">
                <n-space>
                  <n-tag>{{ item.name }}</n-tag>
                  <n-tag v-if="item.status === 1" :bordered="false" type="warning"
                    >未开始</n-tag
                  >
                  <n-tag v-if="item.status === 2" :bordered="false" type="info"
                    >进行中</n-tag
                  >
                  <n-tag v-if="item.status === 3" :bordered="false" type="success"
                    >通过</n-tag
                  >
                  <n-tag v-if="item.status === 4" :bordered="false" type="error"
                    >拒绝</n-tag
                  >
                </n-space>
              </span>
            </template>
            <template #icon>
              <n-icon v-for="a in item.approvalUsers" :key="a.id">
                <n-avatar round size="large" :src="a.avatar" />
              </n-icon>
            </template>
            <template v-if="item.ccUsers !== null && !item.isApplicant" #default>
              <div class="custom-flow-cc">
                <n-avatar size="large">抄送给</n-avatar>
              </div>
              <n-icon v-for="x in item.ccUsers" :key="x.id" style="margin-right: 45px">
                <n-avatar round size="large" :src="x.avatar" />
              </n-icon>
              <div v-if="item.applyOpinion" style="margin-top: 6px">
                <n-alert title="批复意见" type="info">
                  {{ item.applyOpinion }}
                </n-alert>
              </div>
            </template>
          </n-timeline-item>
        </n-timeline>
        <template #footer>
          <n-space>
            <n-button ghost icon-placement="left" @click="handleCloseModel">
              取消
            </n-button>
            <n-button
              v-if="opsType !== 'detail'"
              type="primary"
              :loading="formBtnLoading"
              @click="handleSubmitFlow"
              >提交</n-button
            >
          </n-space>
        </template>
      </n-drawer-content>
    </n-drawer>
  </div>
</template>

<script lang="ts" setup>
import { reactive, ref, h, unref, onMounted } from "vue";
import { useMessage, useDialog } from "naive-ui";
import type { CollapseProps } from "naive-ui";
import { BasicForm, FormSchema, useForm } from "@/components/Form/index";
import { BasicTable, TableAction } from "@/components/Table";
import {
  page,
  save,
  update,
  remove,
  nodeTasks,
  detail as busDetail,
} from "@/api/flow/flowBusiness";
import { list as groupListApi } from "@/api/flow/flowGroup";
import { list as modelListApi, detail } from "@/api/flow/flowModel";
import { usersPages } from "@/api/system/user";
import { columns } from "./columns";
import {
  DeleteOutlined,
  EditOutlined,
  SnippetsOutlined,
  PlusOutlined,
  SearchOutlined,
  EnterOutlined,
} from "@vicons/antd";
import { ResultEnum } from "@/enums/httpEnum";
import MossEmpty from "../../../components/Custom/MossEmpty.vue";
import ModelCard from "../../../components/Custom/ModelCard.vue";
import CustomTitle from "@/components/Custom/CustomTitle.vue";
import GenerateForm from "../../../components/naiveui/components/generate/GenerateForm.vue";
import { userColumns } from "./userColumns";
const message = useMessage();
const actionRef = ref();
const actionUserRef = ref();
const showModal = ref(false);
const formBtnLoading = ref(false);
const editTitle = ref("");
// add upd detail
const opsType = ref<string>("add");
const dialog = useDialog();
const groupList = ref<any[]>([]);
const modelList = ref<any[]>([]);
const groupListOptions = ref<any[]>([]);
const modelListOptions = ref<any[]>([]);
const generateFormRef = ref<any>(null);
const widgetForm = ref<any>(null);
const currentModel = ref<any>(null);
const tasks = ref<any[]>([]);
const detailTasks = ref<any[]>([]);
const searchName = ref<string>("");
const currentTaskId = ref<string>("");
const defaultValueRef = () => ({
  id: null,
  /** 流程分组ID*/
  flowGroupId: null,
  /** 模型表单原始数据*/
  originalFormData: "",
  /**模型表单数据*/
  formData: "",
  /**流程模型ID*/
  flowModelId: null,
  /**流程任务*/
  nodeTasks: null,
});
let fromValues = reactive(defaultValueRef());
/**
 * 表格查询参数定义
 */
const schemas: FormSchema[] = [
  /**查询参数*/
  {
    field: "flowGroupId",
    component: "NSelect",
    label: "流程分组",
    componentProps: {
      placeholder: "请选择流程分组",
      options: groupListOptions,
    },
  },
  {
    field: "flowModelId",
    component: "NSelect",
    label: "流程模型",
    componentProps: {
      placeholder: "请选择流程模型",
      options: modelListOptions,
    },
  },
];
/**
 * 表格查询注册
 */
const [register, { getFieldsValue }] = useForm({
  gridProps: { cols: "1 s:1 m:2 l:3 xl:4 2xl:4" },
  labelWidth: 120,
  schemas,
});
const actionColumn = reactive({
  width: 250,
  title: "操作",
  key: "action",
  fixed: "right",
  render(record) {
    return h(TableAction as any, {
      style: "text",
      actions: createActions(record),
    });
  },
});

function createActions(record) {
  return [
    {
      label: "删除",
      type: "error",
      // 配置 color 会覆盖 type
      color: "red",
      icon: DeleteOutlined,
      onClick: handleDelete.bind(null, record),
      // 根据业务控制是否显示 isShow 和 auth 是并且关系
      ifShow: () => {
        return true;
      },
      // 根据权限控制是否显示: 有权限，会显示，支持多个
      //auth: ['basic_list'],
    },
    {
      label: "编辑",
      type: "primary",
      icon: EditOutlined,
      onClick: handleEdit.bind(null, record, "upd"),
      ifShow: () => {
        return true;
      },
      //auth: ['basic_list'],
    },
    {
      label: "详情",
      type: "success",
      icon: SnippetsOutlined,
      onClick: handleEdit.bind(null, record, "detail"),
      ifShow: () => {
        return true;
      },
      //auth: ['basic_list'],
    },
  ];
}
const loadDataTable = async (res: any) => {
  return await page({ ...getFieldsValue(), ...res });
};

function onCheckedRow(rowKeys: any[]) {
  console.log(rowKeys);
}

function reloadTable() {
  actionRef.value.reload();
}
const handleItemHeaderClick: CollapseProps["onItemHeaderClick"] = async ({}) => {
  generateFormRef.value
    ?.getData()
    .then(async (data) => {
      const updatedJson = convertwidgetForm(data);
      const modelId =
        opsType.value === "add" ? currentModel.value.id : fromValues.flowModelId;
      tasks.value = await nodeTasks({
        modelId: modelId,
        flowForm: JSON.stringify(updatedJson),
      });
    })
    .catch((error) => {
      console.log("error", error);
    });
};

const handleBusDetail = async (id: number) => {
  const data = await busDetail({ id: id });
  if (data.code !== ResultEnum.SUCCESS) {
    const resultMsg = data.data ? data.data : "";
    message.error(data.msg + "-" + resultMsg);
  }
  if (data.code === ResultEnum.SUCCESS) {
    detailTasks.value = data.data.nodeTasks;
  }
};
/**
 * 查询
 */
function handleSubmit() {
  reloadTable();
}
/**
 * 重置查询
 */
function handleReset() {
  reloadTable();
}
function resetFrom() {
  fromValues = Object.assign(unref(fromValues), defaultValueRef());
}
/**
 * 新增详情model
 * @param record
 * @param addStatus
 */
const handleEdit = (record: Recordable, ops: string) => {
  showModal.value = true;
  opsType.value = ops;
  if (ops === "upd") {
    editTitle.value = "编辑" + record.flowModelName;
    fromValues = Object.assign(fromValues, record);
    widgetForm.value = JSON.parse(record.originalFormData);
  } else if (ops === "detail") {
    editTitle.value = record.flowModelName + "详情";
    widgetForm.value = JSON.parse(record.originalFormData);
    handleBusDetail(record.id);
  }
};
/**
 * 申请流程
 * @param flowModel
 */
const handleApplyFlow = (flowModel: any) => {
  showModal.value = true;
  opsType.value = "add";
  editTitle.value = flowModel.flowModelName;
  currentModel.value = flowModel;
  loadData(flowModel.id);
};
/**
 * 快捷申请数据提交
 */
const handleSubmitFlow = () => {
  generateFormRef.value
    ?.getData()
    .then(async (data) => {
      formBtnLoading.value = true;
      const updatedJson = convertwidgetForm(data);
      fromValues =
        opsType.value === "add"
          ? Object.assign(fromValues, {
              flowGroupId: currentModel.value.flowModelGroup,
              flowModelId: currentModel.value.id,
              originalFormData: JSON.stringify(updatedJson),
              formData: JSON.stringify(data),
              nodeTasks: tasks.value,
            })
          : Object.assign(fromValues, {
              originalFormData: JSON.stringify(updatedJson),
              formData: JSON.stringify(data),
              nodeTasks: tasks.value,
            });
      const result =
        opsType.value === "add"
          ? await save(fromValues)
          : opsType.value === "upd"
          ? await update(fromValues)
          : undefined;
      if (result.code !== ResultEnum.SUCCESS) {
        const resultMsg = result.data ? result.data : "";
        message.error(result.msg + "-" + resultMsg);
        formBtnLoading.value = false;
      }
      if (result.code === ResultEnum.SUCCESS) {
        message.success(result.msg);
        showModal.value = false;
        formBtnLoading.value = false;
        resetFrom();
        reloadTable();
      }
    })
    .catch((error) => {
      formBtnLoading.value = false;
      console.log("error", error);
    });
};
/**
 * 转换表单数据
 * @param data
 */
const convertwidgetForm = (data: any) => {
  return {
    ...widgetForm.value,
    list: widgetForm.value.list.map((item) => {
      if (item.model in data) {
        return {
          ...item,
          options: {
            ...item.options,
            defaultValue: data[item.model],
          },
        };
      }
      return item;
    }),
  };
};
/**
 * 新增编辑关闭model
 */
function handleCloseModel() {
  resetFrom();
  widgetForm.value = null;
  showModal.value = false;
}
/**
 * 删除确认
 * @param record
 */
function handleDelete(record: Recordable) {
  dialog.warning({
    title: "警告",
    content: `确定删除吗？`,
    positiveText: "确定",
    negativeText: "取消",
    onPositiveClick: async () => {
      const data = await remove({ id: record.id });
      if (data.code !== ResultEnum.SUCCESS) {
        const resultMsg = data.data ? data.data : "";
        message.error(data.msg + "-" + resultMsg);
      }
      if (data.code === ResultEnum.SUCCESS) {
        message.success(data.msg);
        reloadTable();
      }
    },
  });
}
/**
 * 加载流程数据
 */
const loadFlowGroupAndModel = async () => {
  const groupData = await groupListApi();
  groupList.value = groupData;
  groupListOptions.value = groupData.map((item) => ({
    label: item.groupName,
    value: item.id,
  }));
  const modelData = await modelListApi();
  modelList.value = modelData;
  modelListOptions.value = modelData.map((item) => ({
    label: item.flowModelName,
    value: item.id,
  }));
};
/**
 * 加载form数据
 */
const loadData = async (id: number) => {
  const data = await detail({ id: id });
  widgetForm.value = JSON.parse(data.flowModelForm);
};

const loadUserDataTable = async (res: any) => {
  return await usersPages({
    ...{ name: searchName.value },
    ...res,
    ...{ showTenant: true },
  });
};
function reloadUserTable() {
  actionUserRef.value.reload();
}
const handleChange = (v: string) => {
  searchName.value = v;
  reloadUserTable();
};
const actionColumnCcToUser = reactive({
  title: "操作",
  key: "action",
  fixed: "right",
  render(record) {
    return h(TableAction as any, {
      style: "text",
      actions: createActionsCcToUser(record),
    });
  },
});
function createActionsCcToUser(record) {
  return [
    {
      label: "选择",
      type: "primary",
      icon: PlusOutlined,
      onClick: onCheckedRowCcToUser.bind(null, record),
      ifShow: () => {
        return true;
      },
    },
  ];
}
function onCheckedRowCcToUser(record: Recordable) {
  const task = tasks.value.find((task) => task.taskId === currentTaskId.value);
  if (task) {
    task.ccUsers.push({ id: record.id, name: record.name, avatar: record.avatar });
  }
}
const handleShowCcToUser = (taskId: string) => {
  currentTaskId.value = taskId;
};
onMounted(() => {
  loadFlowGroupAndModel();
});
</script>

<style lang="less" scoped>
.custom-flow-cc {
  width: 60px;
  height: 40px;
  display: flex;
  align-items: center;
  float: left;
}
</style>
